package com.link4a.doms.service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.link4a.doms.dao.handler.MenuHandler;
import com.link4a.doms.dao.handler.UserHandler;
import com.link4a.doms.exception.BusinessException;
import com.link4a.doms.exception.ValidationException;
import com.link4a.doms.model.Module;
import com.link4a.doms.model.User;
import com.link4a.doms.util.MD5Util;
import com.link4a.doms.vo.UserCondition;
import com.link4a.doms.web.SessionContext;

@Service
public class UserService {
	
	private Logger log = LoggerFactory.getLogger(getClass());

	@Autowired
	private UserHandler userHandler;
	@Autowired
	private MenuHandler menuHandler;
	@Autowired
	private SessionContext sessionContext;
	@Autowired
	private FreemarkerService templateService;
	@Autowired
	private MailService mailService;

	public Object findPage(UserCondition condition) {
		return userHandler.findPage(condition);
	}

	public void delete(String username) {
		userHandler.delete(username);
	}

	public void create(User user) throws ValidationException {
		if (userHandler.findByName(user.getUsername()) != null) {
			throw new ValidationException(ValidationException.DATA_DUPLICATED);
		} else {
			// 使用MD5将密码明文加密
			String encryptedPassword = MD5Util.encrypt(user.getPassword());
			user.setPassword(encryptedPassword);			
			userHandler.create(user);
		}
	}

	public void update(User user) {		
		// 使用MD5将密码明文加密
		if(!"".equals(user.getPassword()) && user.getPassword() !=null){
			String encryptedPassword = MD5Util.encrypt(user.getPassword());
			user.setPassword(encryptedPassword);
		}
		userHandler.update(user);
	}

	public User findByUsername(String username) {
		return userHandler.findByName(username);
	}

	public void login(String username, String password) throws BusinessException {
		User user = findByUsername(username);
		if (user == null) {
			throw new BusinessException("用户名不存在");
		}

		// 使用MD5将密码明文加密
		String encryptedPassword = MD5Util.encrypt(password);
		if (!user.getPassword().equals(encryptedPassword)) {
			throw new BusinessException("密码错误");
		}

		userHandler.updateLastVisitTime(username);
		
		List<Module> roleMenus = menuHandler.queryRoleMenus(user.getRoleId());
		List<String> rolePermissions = menuHandler.queryRolePermissions(user.getRoleId());
		sessionContext.onUserLogin(user, roleMenus, rolePermissions);
	}

	public void sendResetMail(String username, String url) throws BusinessException {
		User user = findByUsername(username);
		if (user == null) {
			throw new BusinessException("用户名不存在");
		}
		String applyCode = UUID.randomUUID().toString();
		String link = url + "/login/reset/" + username + "/" + applyCode;
		Map<String, Object> models = new HashMap<String, Object>();
		models.put("link", link);
		models.put("time", new Date());
		models.put("date", new Date());
		try {
			String mailBody = templateService.mergeTemplateIntoString("template/password", models, java.util.Locale.SIMPLIFIED_CHINESE);
			mailService.send(user.getEmail(), "找回密码", mailBody);
			
			user.setApplyCode(applyCode);
			user.setApplyTime(new Date());
			userHandler.updateApplyCode(username, applyCode);
		} catch (Throwable e) {
			log.error("", e);
			throw new BusinessException("发送邮件失败，请检查邮箱是否正确！");
		}
	}
	
	public String validateApplyCode(String username, String applyCode) {
		User user = findByUsername(username);
		
		if (user == null) {
			return "用户名无效";
		}
		if (StringUtils.isBlank(user.getApplyCode()) || !user.getApplyCode().equals(applyCode)) {
			return "验证码无效，请重新申请找回密码";
		}
		if (user.getApplyTime() == null || userHandler.isExpire(user.getApplyTime())) {
			return "验证码已过期，请重新申请找回密码";
		}
		return null;
	}
	
	public void resetPassword(String applyCode, String password) {
		// 使用MD5将密码明文加密
		String encryptedPassword = MD5Util.encrypt(password);
		userHandler.resetPassword(applyCode, encryptedPassword);
	}

}
